#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <fcntl.h>    /* For O_* constants */
#include <sys/stat.h> /* For mode constants */
#include <semaphore.h>

/*
练习5：有4个小孩，每个小孩的任务就是领取生活费1000，回学校之前，先在银行卡中搞 2000块钱，2个线程退出，2个线程进去条件变量中等待，父亲再打钱1000，唤醒所有的小孩起来拿钱， 过一会，再打1000块钱，再唤醒最后一个小孩起来拿钱赶紧走人上学。

*/

// 1、定义一把互斥锁
pthread_mutex_t mutex;
// 1）定义一个条件变量
pthread_cond_t cond;

int money = 2000; // 银行卡里面的初始值 --共享资源 --临界资源

// 线程的例程函数
void *routine1(void *arg)
{
    pthread_mutex_lock(&mutex); // 上锁

    // 条件不满足的时候进入条件变量中等待
    while (money < 1000)
    {
        printf("routine1 加入条件变量中等待\n");
        pthread_cond_wait(&cond, &mutex); // 1 解锁 --阻塞等待
    }
    money -= 1000;
    printf("routine1 拿到钱了，当前银行卡余额:%d\n", money);

    pthread_mutex_unlock(&mutex); // 解锁

    // 主动退出 --走人
    pthread_exit(NULL);
}

// 线程的例程函数
void *routine2(void *arg)
{
    pthread_mutex_lock(&mutex); // 上锁

    // 条件不满足的时候进入条件变量中等待
    while (money < 1000)
    {
        printf("routine2 加入条件变量中等待\n");
        pthread_cond_wait(&cond, &mutex); // 1 解锁 --阻塞等待
    }
    money -= 1000;
    printf("routine2 拿到钱了，当前银行卡余额:%d\n", money);
    pthread_mutex_unlock(&mutex); // 解锁

    // 主动退出
    pthread_exit(NULL);
}
// 线程的例程函数
void *routine3(void *arg)
{
    pthread_mutex_lock(&mutex); // 上锁

    // 条件不满足的时候进入条件变量中等待
    while (money < 1000)
    {
        printf("routine3 加入条件变量中等待\n");
        pthread_cond_wait(&cond, &mutex); // 1 解锁 --阻塞等待
    }
    money -= 1000;
    printf("routine3 拿到钱了，当前银行卡余额:%d\n", money);
    pthread_mutex_unlock(&mutex); // 解锁

    // 主动退出
    pthread_exit(NULL);
}
// 线程的例程函数
void *routine4(void *arg)
{
    pthread_mutex_lock(&mutex); // 上锁

    // 条件不满足的时候进入条件变量中等待
    while (money < 1000)
    {
        printf("routine4 加入条件变量中等待\n");
        pthread_cond_wait(&cond, &mutex); // 1 解锁 --阻塞等待 --被唤醒了
    }
    money -= 1000;
    printf("routine4 拿到钱了，当前银行卡余额:%d\n", money);
    pthread_mutex_unlock(&mutex); // 解锁

    // 主动退出
    pthread_exit(NULL);
}
int main()
{
    // 2、初始化互斥锁
    pthread_mutex_init(&mutex, NULL);
    // 2）初始化 条件变量
    pthread_cond_init(&cond, NULL);

    pthread_t thead1;
    pthread_create(&thead1, NULL, routine1, NULL);
    pthread_t thead2;
    pthread_create(&thead2, NULL, routine2, NULL);
    pthread_t thead3;
    pthread_create(&thead3, NULL, routine3, NULL);
    pthread_t thead4;
    pthread_create(&thead4, NULL, routine4, NULL);

    // 主线程
    int i;
    for (i = 0; i < 5; i++) // 等待5s,之后，父亲过来打钱了
    {
        printf("当前延时%d\n", i);
        sleep(1);
    }
    printf("父亲第一次准备打钱了.....\n");
    // 根据子线程的状态 在这里判断当前有没有线程在等待
    pthread_mutex_lock(&mutex);   // 上锁
    money += 1000;                // 打钱
    pthread_mutex_unlock(&mutex); // 解锁
    // 父亲拿着喇叭 全部唤醒 所有在条件变量中等待的孩子
    pthread_cond_broadcast(&cond);

    for (i = 0; i < 5; i++) // 等待5s,之后，父亲过来打钱了
    {
        printf("当前延时%d\n", i);
        sleep(1);
    }
    printf("父亲第二次准备打钱了.....\n");
    pthread_mutex_lock(&mutex);   // 上锁
    money += 1000;                // 打钱
    pthread_mutex_unlock(&mutex); // 解锁
    // 父亲拿着喇叭 全部唤醒 所有在条件变量中等待的孩子
    pthread_cond_broadcast(&cond);

    pthread_join(thead1, NULL);
    pthread_join(thead2, NULL);
    pthread_join(thead3, NULL);
    pthread_join(thead4, NULL);

    // 销毁互斥锁
    pthread_mutex_destroy(&mutex);
    // 销毁条件变量
    pthread_cond_destroy(&cond);

    return 0;
}
